﻿// Copyright © Microsoft Corporation.  All Rights Reserved.
// This code released under the terms of the 
// Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;

namespace TheOliver.Controls
{
    public class DeepZoomBehavior : Behavior<MultiScaleImage>
    {
        MultiScaleImage _msi;
        Point _lastMousePos = new Point();
        double _zoom = 1;
        bool _mouseButtonPressed = false;
        bool _mouseIsDragging = false;
        Point _dragOffset;
        Point _currentPosition;

        private double ZoomFactor
        {
            get { return _zoom; }
            set { _zoom = value; }
        }

        protected override void OnAttached()
        {
            _msi = this.AssociatedObject;

            _msi.MouseMove += delegate(object sender, MouseEventArgs e)
            {
                if (_mouseButtonPressed)
                {
                    _mouseIsDragging = true;
                }
                _lastMousePos = e.GetPosition(_msi);
            };

            _msi.MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs e)
            {
                _mouseButtonPressed = true;
                _mouseIsDragging = false;
                _dragOffset = e.GetPosition(_msi);
                _currentPosition = _msi.ViewportOrigin;
            };

            _msi.MouseLeave += delegate(object sender, MouseEventArgs e)
            {
                _mouseIsDragging = false;
            };

            _msi.MouseLeftButtonUp += delegate(object sender, MouseButtonEventArgs e)
            {
                _mouseButtonPressed = false;
                if (_mouseIsDragging == false)
                {
                    bool shiftDown = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift;

                    if (shiftDown)
                    {
                        ZoomFactor = 0.5;
                    }
                    else
                    {
                        ZoomFactor = 2.0;
                    }
                    Zoom(ZoomFactor, _lastMousePos);
                }
                _mouseIsDragging = false;
            };

            _msi.MouseMove += delegate(object sender, MouseEventArgs e)
            {
                if (_mouseIsDragging)
                {
                    Point newOrigin = new Point();
                    newOrigin.X = _currentPosition.X - (((e.GetPosition(_msi).X - _dragOffset.X) / _msi.ActualWidth) * _msi.ViewportWidth);
                    newOrigin.Y = _currentPosition.Y - (((e.GetPosition(_msi).Y - _dragOffset.Y) / _msi.ActualHeight) * _msi.ViewportWidth);
                    _msi.ViewportOrigin = newOrigin;
                }
            };

            _msi.MouseWheel += (s, e) =>
            {
                e.Handled = true;
                if (e.Delta > 0)
                {
                    ZoomFactor = 1.2;
                }
                else
                {
                    ZoomFactor = .80;
                }

                Zoom(ZoomFactor, _lastMousePos);
            };
        }

        public void Zoom(double zoom, Point pointToZoom)
        {
            Point logicalPoint = _msi.ElementToLogicalPoint(pointToZoom);
            _msi.ZoomAboutLogicalPoint(zoom, logicalPoint.X, logicalPoint.Y);
        }


    }
}
